package com.imooc.coupon.service.impl;

import com.imooc.coupon.constant.Constant;
import com.imooc.coupon.entity.CouponTemplate;
import com.imooc.coupon.service.IAsyncService;
import com.imooc.coupon.dao.CouponTemplateDao;
import lombok.extern.slf4j.Slf4j;

import org.apache.commons.lang3.RandomStringUtils;


import org.apache.commons.lang3.time.StopWatch;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @Author Administrator
 * @Date 2021/10/24 15:52
 * @Version 1.0
 */
@Slf4j
@Service
public class ASyncServiceImpl implements IAsyncService {

    @Autowired
    private CouponTemplateDao templateDao;
    @Autowired
    private StringRedisTemplate redisTemplate;

    @Async("getAsyncExecutor")
    @Override
    public void asyncConstructCouponByTemplate(CouponTemplate template) {
        StopWatch watch = StopWatch.createStarted();
        Set<String> couponCodes = buildCouponCode(template);
        //redis key
        String redisJKey = String.format("%s%s", Constant.RedisPrefix.COUPON_TEMPLATE, template.getId());
        log.info("Push CouponCode To redis :{}", redisTemplate.opsForList().rightPushAll(redisJKey, couponCodes));
        template.setAvailable(true);
        templateDao.save(template);
        watch.stop();
        log.info("template");
        //todo 发送短信或者邮件通知优惠券模板可以使用了
        log.info("template is available");
    }

    private Set<String> buildCouponCode(CouponTemplate template) {
        StopWatch watch = StopWatch.createStarted();
        Set<String> result = new HashSet<>(template.getCount());
        //前四位
        String prefix4 = template.getProductLine().getCode().toString() + template.getCategory().getCode();
        String date = new SimpleDateFormat("yyMMdd").format(template.getCreateTime());
        for (int i = 0; i != template.getCount(); ++i) {
            result.add(prefix4 + buildCouponCodeSuffix14(date));
        }
        while (result.size() < template.getCount()) {
            result.add(prefix4 + buildCouponCodeSuffix14(date));
        }
        assert result.size() == template.getCount();
        watch.stop();
        //log.info("Build count",watch.   watch.elapsed(TimeUnit.MILLISECONDS));
        return result;
    }

    /**
     * 构造优惠券码的后14位
     *
     * @param date
     * @return
     */
    private String buildCouponCodeSuffix14(String date) {
        char[] bases = new char[]{'1', '2', '3', '4', '5', '6', '7', '8', '9'};
        //中间6位
        List<Character> chars = date.chars().mapToObj(e -> (char) e).collect(Collectors.toList());
        //重新洗牌
        Collections.shuffle(chars);
        String mid6 = chars.stream().map(Object::toString).collect(Collectors.joining());
        //后八位
        String suffix8 = RandomStringUtils.random(1, bases) + RandomStringUtils.randomNumeric(7);
        return mid6 + suffix8;
    }
}
